﻿using Aribaccio;
using BDPAutodetect.DataService;
using BDPAutodetect.Device;
using BDPAutodetect.Models;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BDPAutodetect.Mgrcore
{
    /// <summary>
    /// 检测记录管理
    /// </summary>
    public class DetectRecordManager : BaseManager
    {
        /// <summary>
        /// 检测数据操作实例
        /// </summary>
        protected IDataServiceDetect DataService { get; set; }
        /// <summary>
        /// 用户管理操作
        /// </summary>
        protected UserManager UserMgr { get; set; }
        /// <summary>
        /// 工位管理
        /// </summary>
        protected StationManager StationMgr { get; set; }
        /// <summary>
        /// 检测任务线程
        /// </summary>
        protected PeriodicTaskManual MonitorTask { get; set; }
        /// <summary>
        /// 存储检测数据队列
        /// </summary>
        protected ConcurrentQueue<MDetectRecordDto> StoreDataQueue { get; set; }
        /// <summary>
        /// 检测统计数据
        /// </summary>
        public List<MStationDetectTotal> DetectTotals { get; protected set; }
        /// <summary>
        /// 是否有效存在信息
        /// </summary>
        public bool IsValid => this.DetectTotals != null && this.DetectTotals.Count > 0;

        /// <summary>
        /// 构造函数[注入]
        /// </summary>
        public DetectRecordManager(IDataServiceDetect argDataService, StationManager argStationManager, UserManager argUserManager)
            : base("检测记录管理中心")
        {
            this.DataService = argDataService;
            this.UserMgr = argUserManager;
            this.StationMgr = argStationManager;
            this.DetectTotals = new List<MStationDetectTotal>();
            this.StoreDataQueue = new ConcurrentQueue<MDetectRecordDto>();
            this.MonitorTask = new PeriodicTaskManual($"检测记录存储数据任务", 20, MonitorTaskAction, true, true);

        }

        /// <summary>
        /// 初始化
        /// </summary>
        public override async Task Initialize()
        {
            if (this.IsValid) return;
            if (this.DetectTotals == null) this.DetectTotals = new List<MStationDetectTotal>();
            //获取数据库数据
            var resultDatas = this.DataService.SelectModelItemsTask<TDetectRecordTotal>();
            await resultDatas.ConfigureAwait(false);
            if (resultDatas == null || !resultDatas.Result.ResultState || resultDatas.Result.Data == null || resultDatas.Result.Data.Count <= 0) return;

            foreach (var stationItem in resultDatas.Result.Data.OrderBy(v => v.ID))
            {
                if (stationItem == null) continue;

                var station = this.StationMgr.GetStation(stationItem.StationID);
                if (station == null) continue;

                this.DetectTotals.Add(new MStationDetectTotal()
                {
                    ID = stationItem.ID,
                    Station = station,
                    DetectCount = stationItem.DetectCount,
                    DetectDuration = stationItem.DetectDuration                  
                });
            }
        }

        /// <summary>
        /// 保存检测记录数据
        /// </summary>
        public void SaveData(MStationDetectDto argDetectDto)
        {
            lock (argDetectDto)
            {
                this.StoreDataQueue.Enqueue(new MDetectRecordDto()
                {
                    IsTotalOnly = false,
                    OperateType = DBOperateType.Insert,
                    OperateData = argDetectDto
                });
                this.SaveData(argDetectDto.TotalData);
            }
        }

        /// <summary>
        /// 保存检测统计数据
        /// </summary>
        /// <param name="argTotalData"></param>
        public void SaveData(MStationDetectTotal argTotalData)
        {
            lock (argTotalData)
            {
                this.StoreDataQueue.Enqueue(new MDetectRecordDto()
                {
                    IsTotalOnly = true,
                    OperateType = argTotalData.ID > 0 ? DBOperateType.Update : DBOperateType.Insert,
                    OperateTotal = argTotalData
                });
            }
        }

        /// <summary>
        /// 查询检测记录信息
        /// </summary>
        /// <param name="argQueryData">查询条件数据模型实例</param>
        /// <returns></returns>
        public List<TDetectRecordData>? QueryDetectRecordData(QueryRecordDto argQueryData)
        {
            if (argQueryData == null || argQueryData.StationType == DeviceStationType.None) return default;

            MStation? station = this.StationMgr.GetStation(argQueryData.StationType);
            if (station == null) return default;

            //获取数据库数据 && v.SampleDateTime >= argQueryData.StartDateTime && v.SampleDateTime <= argQueryData.EndDateTime
            ResultList<TDetectRecordData> resultDatas = new ResultList<TDetectRecordData>();
            switch (argQueryData.Status)
            {
                case DetectResultStatus.None:
                    resultDatas = this.DataService.SelectModelItems<TDetectRecordData, int>(
                        v => v.StationID == station.ID && v.SampleDateTime >= argQueryData.StartDateTime && v.SampleDateTime <= argQueryData.EndDateTime,
                        o => o.ID, ExecuteStatus.No);
                    break;
                case DetectResultStatus.Pass:
                    resultDatas = this.DataService.SelectModelItems<TDetectRecordData, int>(
                        v => v.StationID == station.ID && v.SampleDateTime >= argQueryData.StartDateTime && v.SampleDateTime <= argQueryData.EndDateTime && v.StatusFlag == 0,
                        o => o.ID, ExecuteStatus.No);
                    break;
                case DetectResultStatus.Fail:
                    resultDatas = this.DataService.SelectModelItems<TDetectRecordData, int>(
                        v => v.StationID == station.ID && v.SampleDateTime >= argQueryData.StartDateTime && v.SampleDateTime <= argQueryData.EndDateTime && v.StatusFlag == 1,
                        o => o.ID, ExecuteStatus.No);
                    break;
            }
            return resultDatas.Data;
        }

        /// <summary>
        /// 获取统计数据
        /// </summary>
        /// <param name="argStationType">工位类型</param>
        /// <returns></returns>
        public MStationDetectTotal? GetDetectTotalData(DeviceStationType argStationType)
        {
            if (!this.IsValid || argStationType == DeviceStationType.None) return null;
            return this.DetectTotals.FirstOrDefault(v => v.Station.StationType == argStationType);
        }

        /// <summary>
        /// 获取工位信息
        /// </summary>
        /// <returns></returns>
        public List<MStation> GetStations()
        {
            return this.StationMgr.Stations;
        }

        /// <summary>
        /// 执行线程任务
        /// </summary>
        protected void MonitorTaskAction()
        {
            if (this.DataService == null) return;
            if (this.StoreDataQueue.Count <= 0) return;

            while (this.StoreDataQueue.TryDequeue(out MDetectRecordDto? storeData))
            {
                if (storeData == null) continue;
                if (storeData.IsTotalOnly)
                {
                    SaveDetectRecordTotal(storeData.OperateTotal, storeData.OperateType);
                }
                else
                {
                    SaveDetectRecord(storeData.OperateData);
                }
            }
        }

        /// <summary>
        /// 保存检测记录数据
        /// </summary>
        /// <param name="argDetectDto"></param>
        /// <returns></returns>
        protected void SaveDetectRecord(MStationDetectDto? argDetectDto)
        {
            if (argDetectDto == null) return;
            //存储检测指标记录信息
            TDetectRecordData detectRecordData = new TDetectRecordData(argDetectDto.StartDateTime, argDetectDto.Station.ID)
            {
                SampleDuration = argDetectDto.DetectTimeDiff,
                Barcode = argDetectDto.Barcode ?? string.Empty,
                ParameterID = argDetectDto.ParameterData?.ID ?? 0,
                StatusFlag = argDetectDto.DetectResultStatus == DetectResultStatus.Pass ? 0 : 1,
                UserID = this.UserMgr?.LoginUser?.ID ?? 0
            };
            foreach (var item in argDetectDto.TargetDatas)
            {
                switch (item.TargetType)
                {
                    case DeviceTargetType.Customer_DebugModeCheck:
                        detectRecordData.DebugModeStart = item.DetectResultValue;
                        break;
                    case DeviceTargetType.Customer_SoftwareVersion:
                        detectRecordData.SoftwareVersion = item.DetectResultValue;
                        break;
                    case DeviceTargetType.Customer_NTCTemperature:
                        detectRecordData.NTCTemperature = item.ToDataNumber();
                        break;
                    case DeviceTargetType.Customer_WitchBarrelMicro:
                        detectRecordData.WitchBarrelMicro = item.DetectResultValue;
                        break;
                    case DeviceTargetType.Customer_WitchTipping:
                        detectRecordData.WitchTipping = item.DetectResultValue;
                        break;
                    case DeviceTargetType.Customer_CompressorPower:
                        detectRecordData.CompressorPower = item.ToDataNumber();
                        break;
                    case DeviceTargetType.Customer_CompressorCurrent:
                        detectRecordData.CompressorCurrent = item.ToDataNumber();
                        break;
                    case DeviceTargetType.Customer_CompressorVoltage:
                        detectRecordData.CompressorCurrent = item.ToDataNumber();
                        break;
                    case DeviceTargetType.Customer_CondenserFanPower:
                        detectRecordData.CondenserFanPower = item.ToDataNumber();
                        break;
                    case DeviceTargetType.Customer_MotorPower:
                        detectRecordData.MotorPower = item.ToDataNumber();
                        break;
                    case DeviceTargetType.Customer_MotorCurrent:
                        detectRecordData.MotorCurrent = item.ToDataNumber();
                        break;
                    case DeviceTargetType.Customer_MotorVoltage:
                        detectRecordData.MotorVoltage = item.ToDataNumber();
                        break;
                    case DeviceTargetType.Customer_EnvironmentTemperature:
                        detectRecordData.EnvironmentTemperature = item.ToDataNumber();
                        break;
                }
            }
            this.DataService.Insert(detectRecordData);
        }

        /// <summary>
        /// 保存检测统计数据
        /// </summary>
        /// <param name="argTotalData"></param>
        /// <param name="argOperateType"></param>
        protected void SaveDetectRecordTotal(MStationDetectTotal? argTotalData, DBOperateType argOperateType)
        {
            if (argTotalData == null) return;
            var detectRecordTotal = argTotalData.CloneTData();
            switch (argOperateType)
            {
                case DBOperateType.Insert:
                    this.DataService.Insert(detectRecordTotal);
                    break;
                case DBOperateType.Update:
                    this.DataService.UpdateWhere(detectRecordTotal, v => v.ID == detectRecordTotal.ID);
                    break;
            }
        }
    }
}
